package com.xpxrule;

import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Expression;
import com.googlecode.aviator.runtime.function.AbstractFunction;
import com.xpxrule.constant.FieldType;
import com.xpxrule.dataobject.bo.AviatorMatchBo;
import com.xpxrule.dataobject.bo.RuleConditionItemBo;
import com.xpxrule.dataobject.dao.ModelItem;
import com.xpxrule.dataobject.dao.Rule;
import com.xpxrule.dataobject.vo.RuleVo;
import com.xpxrule.function.AviatorCustomFunctionContext;
import com.xpxrule.util.AviatorFieldUtil;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

public class AviatorExecuteUtil {
    public static String AVIATOR_RIGHT_PREFIX = "aviatorRightPrefix";
    public static final String AVIATOR_PREFIX_FORMAT = "%s_%s";

    public static void aviatorRegisterCustomFunction() {
        // 注册自定义函数
        ConcurrentHashMap<String, AbstractFunction> customFunctionMap = AviatorCustomFunctionContext.getCustomFunctionMap();
        customFunctionMap.forEach((key, value) -> {
            AviatorEvaluator.addFunction(value);
        });
    }

    /**
     * 将规则翻译为Aviator语法并执行
     * 
     * @param ruleVo
     * @param params
     * @return
     */
    public static AviatorMatchBo isMatch(RuleVo ruleVo, Map<String, Object> params) throws Exception {
        AviatorMatchBo matchBo = new AviatorMatchBo();
        matchBo.setRuleId(Long.valueOf(ruleVo.getId()));
        List<RuleConditionItemBo> conditionItemList = ruleVo.getConditionDetail();
        Map<String, Object> targetParams = new HashMap<>();
        conditionItemList.forEach(conditionItem -> {
            String fieldKey = conditionItem.getFieldKey();
            targetParams.put(fieldKey, params.getOrDefault(fieldKey, null));
        });
        // 将规则与对应条件翻译为aviator语句
        /**
         * 思路变更，采用参数模式，整体步骤如下
         * 1：获取aviator环境
         * 2：将param转为对应字段类型的string
         * 3：执行aviator语句
         */
        Map<String, FieldType> fieldTypeMap = AviatorFieldUtil.getFieldTypeMap(ruleVo);
        String executeStr = AviatorFieldUtil.translateAviatorSyntax(conditionItemList, targetParams);// 此处为右值
        matchBo.setAviatorScript(executeStr);
        Map<String, Object> envMap = AviatorFieldUtil.translateParamsField(params, fieldTypeMap, conditionItemList);// 此处为左值
        // 执行aviator语句
        Expression compileExp = AviatorEvaluator.compile(executeStr, true);
        boolean result = (boolean) compileExp.execute(envMap);
        matchBo.setMatchResult(result);
        matchBo.setConditionItemList(conditionItemList);
        matchBo.setParams(params);
        return matchBo;
    }

    /**
     * 过滤规则，只保留符合时间范围的规则
     * 
     * @param rules
     * @param occurrenceTime
     * @return
     */
    public static List<Rule> filterRuleByTimeRange(List<Rule> rules, Date occurrenceTime) {
        if (rules.isEmpty()) {
            return new ArrayList<>();
        }
        // 过滤不符合时间范围的规则
        List<Rule> filterRules = rules.stream()
                .filter(rule -> occurrenceTime.getTime() >= rule.getStartEffectTime().getTime()
                        && (rule.getEndEffectTime() == null
                                || occurrenceTime.getTime() <= rule.getEndEffectTime().getTime()))
                .collect(Collectors.toList());
        return filterRules;
    }

    public static Map<String, Object> filterAndFillFieldByModelItem(Map<String, Object> params, List<ModelItem> conditionModelItemList) {
//        Map<String, Object> result = conditionModelItemList.stream()
//                .collect(Collectors.toMap(
//                        ModelItem::getFieldKey,
//                        modelItem -> params.getOrDefault(modelItem.getFieldKey(), null)));
        Map<String, Object> result = new HashMap<>();
        for (ModelItem modelItem : conditionModelItemList) {
            String fieldKey = modelItem.getFieldKey();
            Object param = params.getOrDefault(fieldKey, null);
            result.put(fieldKey, param);
        }
        return result;
    }
}
